package net.gdface.utils;

import java.util.concurrent.atomic.AtomicReference;

/**
 * 延迟初始化(Lazy initialization)变量封装接口
 * @author guyadong
 *
 * @param <T> 延迟变量类型
 */
public interface ILazyInitVariable<T> {
	/**
	 * 返回延迟初始化的 T 实例 
	 * @return T 实例 
	 */
	public T get();
	public static abstract class BaseLazyVar<T> implements ILazyInitVariable<T>{
		/**
		 * 返回 T 实例
		 * @return T 实例
		 */
		abstract protected T doGet() ;
	}
	/**
	 * @since 2.9.9
	 */
	public abstract class VolatileVar<T,V> extends BaseLazyVar<T>{
		private volatile V  var = null;
		protected abstract V in( T t);
		protected abstract T out(V var);
		@Override
		public T get() {
			// Double-checked locking
			if(null == var){
				synchronized(this){
					if(null == var){
						var = in(doGet());
					}
				}
			}
			return out(var);
		}
	}
	/**
	 * 使用{@link AtomicReference}对变量进行封装，确保值为{@code null}时也只初始化一次
	 * @since 2.9.9
	 */
	public static abstract class VolatileReferenceVar<T> extends VolatileVar<T,AtomicReference<T>>{
		
		/**
		 * 返回不为{@code null}的实例，确保{@link #doGet()}方法只会执行一次
		 */
		@Override
		protected final AtomicReference<T> in(T t) {
			return new AtomicReference<>(t);
		}

		@Override
		protected final T out(AtomicReference<T> var) {
			return var.get();
		}
		
	}
}
